package com.ctgu.demo05.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctgu.demo05.entity.CustomersEntity;
import com.ctgu.demo05.entity.OrdersEntity;
import com.ctgu.demo05.mapper.OrdersMapper;
import com.ctgu.demo05.service.CustomersService;
import com.ctgu.demo05.mapper.CustomersMapper;
import com.ctgu.demo05.utils.ApiResult;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;

/**
* @author Alex2
* @description 针对表【t_customers】的数据库操作Service实现
* @createDate 2025-03-13 10:50:58
*/
@Service
@RequiredArgsConstructor
public class CustomersServiceImpl extends ServiceImpl<CustomersMapper, CustomersEntity>
    implements CustomersService {

    private final OrdersMapper ordersMapper;

    private final TransactionTemplate transactionTemplate;

    /**
     * @Author: Alex
     * @Description: 插入顾客
     */
    @Override
    public ApiResult insertCustomer(String name, BigDecimal balance) {
        CustomersEntity customers = lambdaQuery().eq(CustomersEntity::getName, name).one();
        if (customers != null) {
            return ApiResult.error("该顾客已存在");
        }
        CustomersEntity customersEntity = new CustomersEntity(null, name, balance);
        boolean save = save(customersEntity);
        if (!save) {
            return ApiResult.error("插入顾客失败");
        } else {
            return ApiResult.success("插入顾客成功");
        }
    }

    /**
     * @Author: Alex
     * @Description: 编程式事务
     */
    @Override
    public ApiResult consumer(Integer customerId, BigDecimal amount) {
        CustomersEntity customersEntity = lambdaQuery().eq(CustomersEntity::getId, customerId).one();
        if (customersEntity == null) {
            return ApiResult.error("该顾客不存在");
        }
        if (customersEntity.getBalance().compareTo(amount) < 0) {
            return ApiResult.error("余额不足");
        }
        return transactionTemplate.execute(status -> {      // 开启事务
            // 存在并发问题，查询余额customersEntity.getBalance()在事务外
//                boolean update = lambdaUpdate()
//                        .eq(CustomersEntity::getId, customerId)
//                        .ge(CustomersEntity::getBalance, amount)
//                        .setSql("balance = balance - " + amount)
//                        .update();

            // 不存在并发问题，更新时同时判断余额
            boolean update = lambdaUpdate()
                    .setSql("balance = " +
                            "CASE " +
                            "WHEN balance >= " + amount + " THEN balance - " + amount +
                            " ELSE balance " +
                            "END")
                    .eq(CustomersEntity::getId, customerId)
                    .update();
            if (!update) {
                throw new RuntimeException("扣款失败");     //抛异常，Spring 自动回滚
            }
            OrdersEntity ordersEntity = new OrdersEntity(null, amount, customerId);
            int insert = ordersMapper.insert(ordersEntity);
            if (insert == 0) {
                throw new RuntimeException("订单创建失败");     //抛异常，Spring 自动回滚
            }
            return ApiResult.success("订单创建成功");
        });
    }

    /**
     * @Author: Alex
     * @Description: 注解式事务-乐观锁+原子 SQL
     */
    @Override
    public ApiResult consumerByAnnotation(Integer customerId, BigDecimal amount) {
        CustomersEntity customersEntity = lambdaQuery().eq(CustomersEntity::getId, customerId).one();
        if (customersEntity == null) {
            return ApiResult.error("该顾客不存在");
        }
        if (customersEntity.getBalance().compareTo(amount) < 0) {
            return ApiResult.error("余额不足");
        }
        CustomersService customersService = (CustomersService) AopContext.currentProxy();
        return customersService.updateBalanceAndCreateOrder(customerId, amount);
    }

    @Transactional(rollbackFor = Exception.class)       // 事务由 Spring 自动管理
    public ApiResult updateBalanceAndCreateOrder(Integer customerId, BigDecimal amount) {
        // 不存在并发问题，更新时同时判断余额
        boolean update = lambdaUpdate()
                .setSql("balance = " +
                        "CASE " +
                        "WHEN balance >= " + amount + " THEN balance - " + amount +
                        " ELSE balance " +
                        "END")
                .eq(CustomersEntity::getId, customerId)
                .update();
        if (!update) {
            throw new RuntimeException("扣款失败，事务回滚");    //抛异常，Spring 自动回滚
        }
        // 创建订单
        OrdersEntity ordersEntity = new OrdersEntity(null, amount, customerId);
        int insert = ordersMapper.insert(ordersEntity);
        if (insert == 0) {
            throw new RuntimeException("订单创建失败，事务回滚");  //抛异常，Spring 自动回滚
        }
        return ApiResult.success("订单创建成功");
    }
}